package br.edu.unifei.mestrado.fm;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class Cell {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	private long id;
	private int gain;
	private boolean locked = false;
	private int partition;

	private NetList nets;
	private Cell prev;
	private Cell next;

	public Cell() {
		
	}
	
	public Cell(long idCell) {
		this.id = idCell;
		this.nets = new NetList();
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public int getGain() {
		return gain;
	}

	public void incrementGain() {
		this.gain++;
	}

	public void decrementGain() {
		this.gain++;
	}

	public Block getFromBlock() {
		Block fromBlock = new Block();
		for (Net net : this.getNets()) {
			
			Cell cell1 = net.getCell1();
			long id = cell1.getId();
			if (this.getId() != id // para nao usar a mesma celula base
					&& cell1.getPartition() == this.getPartition()) {
				fromBlock.increment(net);
			}
			Cell cell2 = net.getCell2();
			id = cell2.getId();
			if (this.getId() != id // para nao usar a mesma celula base
					&& cell2.getPartition() == this.getPartition()) {
				fromBlock.increment(net);
			}
		}
		
		fromBlock.print("From Block de " + getId() + ": ");
		return fromBlock;
	}

	public Block getToBlock() {
		Block toBlock = new Block();
		for (Net net : this.getNets()) {

			// TODO: melhorar esse c�digo.
			// tem que fazer um if para n�o usar a mesma celula e depois que achar, da� faz 1 s� if de
			// partition
			Cell cell1 = net.getCell1();
			long id = cell1.getId();
			if (this.getId() != id // para nao usar a mesma celula base
					&& cell1.getPartition() == this.getPartition()) {
				toBlock.increment(net);
			}
			Cell cell2 = net.getCell2();
			id = cell2.getId();
			if (this.getId() != id // para nao usar a mesma celula base
					&& cell2.getPartition() == this.getPartition()) {
				toBlock.increment(net);
			}
		}
		toBlock.print("To   Block de " + getId() + ": ");
		return toBlock;
	}

	public boolean isLocked() {
		return locked;
	}

	public void lock() {
		this.locked = true;
	}

	public int getPartition() {
		return partition;
	}

	public void setPartition(int partition) {
		this.partition = partition;
	}

	public NetList getNets() {
		return nets;
	}

	public void setNets(NetList nets) {
		this.nets = nets;
	}

	public Cell getPrev() {
		return prev;
	}

	public void setPrev(Cell prev) {
		this.prev = prev;
	}

	public Cell getNext() {
		return next;
	}

	public void setNext(Cell next) {
		this.next = next;
	}

	@Override
	public String toString() {
		return id + " p:" + partition + " g:" + gain;
	}

	public void updateGain(Block fromBlock, Block toBlock) {
		logger.info("Atualizando ganhos...");
		for (Net net : this.getNets()) {
			
			//verificar se é 1 mesmo, pq como incrementa, pode ser maior que 1
			//UTIL: é 1 sim, o algoritmo diz que é 1.
			if (fromBlock.getSizeOf(net) == 1) {
				this.incrementGain();
			}
			if (toBlock.getSizeOf(net) == 0) {
				this.decrementGain();
			}
		}
	}
}
